package mbsl.commons.base;

import java.util.ArrayList;
import java.util.List;

import mbsl.commons.Commons;
import mbsl.ui.ImageLoader;
import mbsl.ui.SearchPanel;
import mbsl.util.SWTUtils;
import static mbsl.util.SWTUtils.Direction.*;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Table;

/**
 * The panel on which the ElementController operates.
 */
public class ElementPanel {
	protected ElementPanel(TabFolder pParent, String pTabText) {
		mLabel = new TabItem(pParent, SWT.NONE);
		mTabFocusListeners = new ArrayList<TabFocusListener>();

		// The system to which we are connecting, the tabbed folder in MainFrame, sends out messages to the tabs that are getting focus.
		mLabel.addListener(SWT.FocusIn, new Listener() {
			@Override
			public void handleEvent(Event pEvent) {
				for (TabFocusListener listener : mTabFocusListeners)
					listener.focusGained();
			}
		});
		mLabel.addListener(SWT.FocusOut, new Listener() {
			@Override
			public void handleEvent(Event pEvent) {
				for (TabFocusListener listener : mTabFocusListeners)
					listener.focusLost();
			}
		});
		
		mPanel = new Composite(pParent, SWT.BACKGROUND);
		
		mLabel.setControl(mPanel);
		mLabel.setText(pTabText);
		mPanel.setLayout(new FormLayout());
		
		mTable = new Table(mPanel, SWT.VIRTUAL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);

		mTable.setLayoutData(SWTUtils.getFormData(
				SWTUtils.getMeta(up, 0, TOP_PANEL_HEIGHT), 
				SWTUtils.getMeta(left, 0, 0), 
				SWTUtils.getMeta(right, 100, 0), 
				SWTUtils.getMeta(down, 100, 0)
		));
		mTable.setHeaderVisible(true);

		mTable.addMouseListener(new MouseAdapter() {
			public void mouseDoubleClick(MouseEvent pE) {
				// Double-clicking on a row does the same as clicking the view button, so we send the event there.
				mViewButton.notifyListeners(SWT.Selection, new Event());
			}
		});

		/* This piece is here to fix a table scrolling bug that made the scrolling reset itself half way through.
		 * Unfortunately, this is more of a workaround than a fix, since I've been unable to determine whether it's a
		 * Windows bug, an SWT bug, or something we've caused ourselves. */
/*		mTable.addMouseWheelListener(new MouseWheelListener() {
			@Override
			public synchronized void mouseScrolled(MouseEvent pE) {
				if (mLast < scrollBar.getSelection() && pE.count > 0) {
					scrollBar.setSelection(mLast);
					System.out.println("Ran setselection " + mLast);
				} else if (mLast > scrollBar.getSelection() && pE.count < 0) {
					scrollBar.setSelection(mLast);
					System.out.println("Ran setselection " + mLast);
				} else {
					mLast = scrollBar.getSelection();
					System.out.println("Default " + mLast);
				}
			}
			
			private ScrollBar scrollBar = mTable.getVerticalBar();
			private int mLast;
		});
*/
		mSearchPanel = new SearchPanel(mPanel);
		
		mSearchPanel.getWidget().setLayoutData(SWTUtils.getFormData(200, SWT.DEFAULT, 
				SWTUtils.getMeta(up, 0, MARGIN), 
				SWTUtils.getMeta(right, 100, -MARGIN), 
				SWTUtils.getMeta(down, 0, TOP_PANEL_HEIGHT - MARGIN)
		));
		
		mNewButton = new Button(mPanel, SWT.PUSH);
		
		mNewButton.setLayoutData(SWTUtils.getFormData(BUTTON_WIDTH, SWT.DEFAULT, 
				SWTUtils.getMeta(up, 0, MARGIN), 
				SWTUtils.getMeta(left, 0, MARGIN), 
				SWTUtils.getMeta(down, 0, TOP_PANEL_HEIGHT - MARGIN)
		));
		mNewButton.setText("New");
		
		mViewButton = new Button(mPanel, SWT.PUSH);
		
		mViewButton.setLayoutData(SWTUtils.getFormData(BUTTON_WIDTH, SWT.DEFAULT, 
				SWTUtils.getMeta(up, 0, MARGIN), 
				SWTUtils.getMeta(down, 0, TOP_PANEL_HEIGHT - MARGIN), 
				SWTUtils.getMeta(left, mNewButton, MARGIN)
		));
		mViewButton.setText("View");
		
		setUpMenu();
	}
	public void addNewButtonListener(SelectionListener pListener) {
		mNewButton.addSelectionListener(pListener);
	}
	public void addViewButtonListener(SelectionListener pListener) {
		mViewButton.addSelectionListener(pListener);
	}
	public void addPopUpEditListener(SelectionListener pListener) {
		mPopUpEdit.addSelectionListener(pListener);
	}
	public void addPopUpDeleteListener(SelectionListener pListener) {
		mPopUpDelete.addSelectionListener(pListener);
	}
	public void addTabFocusListener(TabFocusListener pListener) {
		mTabFocusListeners.add(pListener);
	}
	public Table getTable() {
		return mTable;
	}
	protected SearchPanel getSearchPanel() {
		return mSearchPanel;
	}
	
	protected void setUpMenu() {
		Menu menu = new Menu(mTable);
		
		mTable.setMenu(menu);
		
		mPopUpView = new MenuItem(menu, SWT.PUSH);
		mPopUpEdit = new MenuItem(menu, SWT.PUSH);
		mPopUpDelete = new MenuItem(menu, SWT.PUSH);
		
		mPopUpView.setText(Commons.tp.get("common.table.popup.view"));
		mPopUpView.setImage(ImageLoader.getImage(mTable.getDisplay(), "view"));
		mPopUpEdit.setText(Commons.tp.get("common.table.popup.edit"));
		mPopUpEdit.setImage(ImageLoader.getImage(mTable.getDisplay(), "edit"));
		mPopUpDelete.setText(Commons.tp.get("common.table.popup.delete"));
		mPopUpDelete.setImage(ImageLoader.getImage(mTable.getDisplay(), "delete"));
		
		mPopUpView.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent pE) {
				// Once again, we just route the event to the View button on the panel.
				mViewButton.notifyListeners(SWT.Selection, new Event());
			}
		});
	}
	protected TabItem getTabItem() {
		return mLabel;
	}
	
	/** The width of the buttons at the top left of the panel. */
	public static final int BUTTON_WIDTH = 60;
	/** The margin used by the buttons and search field to determine space between and around them selves. */
	public static final int MARGIN = 2;
	/** The height of the tool panel on which we find the buttons and search field. */
	public static final int TOP_PANEL_HEIGHT = 25;

	private TabItem mLabel;
	private Composite mPanel;
	private SearchPanel mSearchPanel;
	private Button mNewButton;
	private Button mViewButton;
	private MenuItem mPopUpView;
	private MenuItem mPopUpEdit;
	private MenuItem mPopUpDelete;
	private Table mTable;
	private List<TabFocusListener> mTabFocusListeners;
}
